/********************************************************************************
 *    Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH    *
 *                                                                              *
 *              This software is distributed under the terms of the             *
 *              GNU Lesser General Public Licence (LGPL) version 3,             *
 *                  copied verbatim in the file "LICENSE"                       *
 ********************************************************************************/
#include "HiMusicUnpackTask.h"
#include "HiMusicUnpackedData.h"
#include "HiDaqUnpackUserFunction.h"
#include "HiDaqFormat.h"
#include "HiDaqInfoData.h"

#include "FairRootManager.h"
#include "FairRunAna.h"
#include "FairRuntimeDb.h"

#include <TClonesArray.h>
// ---- Default constructor -------------------------------------------
HiMusicUnpackTask::HiMusicUnpackTask()
    : FairTask("HiMusicUnpackTask")
{
    LOG(debug) << "Default Constructor of HiMusicUnpackTask";
}
// ---- Constructor with parameters (Optional) ---------------------------
HiMusicUnpackTask::HiMusicUnpackTask(HiDaqUnpackTask* BasicUnpacker, Bool_t savetotree)
    : FairTask("HiMusicUnpackTask"),
    fBasicUnpacker(BasicUnpacker),
    fSaveToTree(savetotree)
{
    LOG(debug) << "Constructor with parameters of HiMusicUnpackTask";
}

// ---- Destructor ----------------------------------------------------
HiMusicUnpackTask::~HiMusicUnpackTask() { 
    LOG(debug) << "Destructor of HiMusicUnpackTask"; 
}

// ----  Initialisation  ----------------------------------------------
void HiMusicUnpackTask::SetParContainers()
{
    LOG(debug) << "SetParContainers of HiMusicUnpackTask";
    // Load all necessary parameter containers from the runtime data base
    /*
    FairRunAna* ana = FairRunAna::Instance();
    FairRuntimeDb* rtdb=ana->GetRuntimeDb();
    
    <HiDaqUnpackTaskDataMember> = (<ClassPointer>*)
      (rtdb->getContainer("<ContainerName>"));
    */
}

// ---- Init ----------------------------------------------------------
InitStatus HiMusicUnpackTask::Init()
{
    LOG(debug) << "Initilization of HiMusicUnpackTask";

    // Get a handle from the IO manager
    FairRootManager* ioman = FairRootManager::Instance();
    if(ioman == 0)
    {
        LOG(error) << "FairRootManager not instantiated!";
        return kERROR;
    }

    fInputFile = fBasicUnpacker->GetInputFileStream();

    fDaqInfoArray = static_cast<TClonesArray*>(ioman->GetObject("HiDaqInfoData"));
    if (!fDaqInfoArray) {
        LOG(warn) << "-W- HiMusicUnpackTask::Init: No Data array!";
        return kERROR;
    }

    // Create the TClonesArray for the output data and register
    fUnpackedArray = new TClonesArray("HiMusicUnpackedData");
    ioman->Register("HiMusicUnpackedData", "HiMusicUnpack", fUnpackedArray, kTRUE);

    // Do whatever else is needed at the initilization stage
    // Create histograms to be filled
    // initialize variables

    return kSUCCESS;
}

// ---- ReInit  -------------------------------------------------------
InitStatus HiMusicUnpackTask::ReInit()
{
    LOG(debug) << "Initilization of HiMusicUnpackTask";
    return kSUCCESS;
}

// ---- Exec ----------------------------------------------------------
void HiMusicUnpackTask::Exec(Option_t* /*option*/) { 
    LOG(debug) << "Exec of HiMusicUnpackTask"; 

    // Clear the output array
    fUnpackedArray->Clear();

    // ----循环读取fDaqInfoArray的数据并处理----------------------------------
    for(int i = 0; i < fDaqInfoArray->GetEntriesFast(); i++){
        HiDaqInfoData* DaqInfo = static_cast<HiDaqInfoData*>(fDaqInfoArray->At(i));
        if (!DaqInfo || DaqInfo->fNPxi == 0) continue;
        uint8_t PXI_id = DaqInfo->fPxiID;
        // ---- 判断是否属于该探测器 ------------------------------
        auto iter = PXI_TO_DETECTOR.find(PXI_id);
        if(iter != PXI_TO_DETECTOR.end() && iter->second == DET_MUSIC){
            fInputFile->seekg(DaqInfo->fFEEAddress, std::ios::beg);
            // ---- 解包数据净荷 ------------------------
            std::array<std::array<uint16_t, 4096>, 9> tmpWaveform;
            for(int j = 0; j < 4096; ++j){
                uint64_t TempData1 = static_cast<uint64_t>(readBE(fInputFile, 8)); 
                uint64_t TempData2 = static_cast<uint64_t>(readBE(fInputFile, 8));

                tmpWaveform[0][j] = TempData2&0x3FFF;
                tmpWaveform[1][j] = (TempData2>>14)&0x3FFF;
                tmpWaveform[2][j] = (TempData2>>28)&0x3FFF;
                tmpWaveform[3][j] = (TempData2>>42)&0x3FFF;
                tmpWaveform[4][j] = ((TempData2>>56)&0xFF) | ((TempData1&0x3F)<<8);
                tmpWaveform[5][j] = TempData1>>6&0x3FFF;
                tmpWaveform[6][j] = TempData1>>20&0x3FFF;
                tmpWaveform[7][j] = TempData1>>34&0x3FFF;
                tmpWaveform[8][j] = TempData1>>48&0x3FFF;
            }
            // HiMusicUnpackedData* MusicUnpackedData = new ((*fUnpackedArray)[fUnpackedArray->GetEntriesFast()]) 
            //     HiMusicUnpackedData(tmpWaveform);
            new ((*fUnpackedArray)[fUnpackedArray->GetEntriesFast()]) 
                HiMusicUnpackedData(DaqInfo->fTimeSliceID,
                                DaqInfo->fPxiID, 
                                DaqInfo->fFeeID, 
                                tmpWaveform);
        }
    }
}

// ---- Finish --------------------------------------------------------
void HiMusicUnpackTask::Finish() { 
    LOG(debug) << "Finish of HiMusicUnpackTask"; 
}

ClassImp(HiMusicUnpackTask);
